/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.spend.service.impl;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.google.common.collect.Lists;
import me.zhengjie.modules.spend.domain.Spend;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.repository.DictDetailRepository;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.modules.utils.FileMover;
import me.zhengjie.modules.utils.utils.DateUtils;
import me.zhengjie.modules.utils.DownExcelTemp;
import me.zhengjie.modules.utils.DownLoadUtil;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.spend.repository.SpendRepository;
import me.zhengjie.modules.spend.service.SpendService;
import me.zhengjie.modules.spend.service.dto.SpendDto;
import me.zhengjie.modules.spend.service.dto.SpendQueryCriteria;
import me.zhengjie.modules.spend.service.mapstruct.SpendMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author yyj
* @date 2022-04-08
**/
@Service
@RequiredArgsConstructor
public class SpendServiceImpl implements SpendService {

    private final SpendRepository spendRepository;
    private final SpendMapper spendMapper;
    private final FileMover fileMover;

    private static String warningInfo = "带*号的列请选择下拉框内的数据，红色字体为必填项";
    @Resource
    private DictDetailRepository dictDetailRepository;

    @Override
    public Map<String,Object> queryAll(SpendQueryCriteria criteria, Pageable pageable){
        Page<Spend> page = spendRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(spendMapper::toDto));
    }

    @Override
    public List<SpendDto> queryAll(SpendQueryCriteria criteria){
        return spendMapper.toDto(spendRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public SpendDto findById(String id) {
        Spend spend = spendRepository.findById(id).orElseGet(Spend::new);
        ValidationUtil.isNull(spend.getId(),"Spend","id",id);
        return spendMapper.toDto(spend);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SpendDto create(Spend resources) {
        resources.setId(IdUtil.simpleUUID()); 
        return spendMapper.toDto(spendRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Spend resources) {
        Spend spend = spendRepository.findById(resources.getId()).orElseGet(Spend::new);
        ValidationUtil.isNull( spend.getId(),"Spend","id",resources.getId());
        spend.copy(resources);
        spendRepository.save(spend);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            spendRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<SpendDto> all, HttpServletResponse response) throws IOException {

        /*获取支付类型的字典详情列表*/
        List<DictDetail> payTypeList = dictDetailRepository.getByDictName("pay_type");
        /*获取花费类型的字典详情列表*/
        List<DictDetail> spendTypeList = dictDetailRepository.getByDictName("spend_type");
        List<Map<String, Object>> list = new ArrayList<>();
        for (SpendDto spend : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("名称", spend.getName());
            map.put("金额", spend.getPrice());
            /*将字典值转化为对应的字典标签*/
            for(DictDetail spendType:spendTypeList){
                if(spendType.getValue().equals(spend.getSpendType())){
                    map.put("花费类型",spendType.getLabel());
                }
            }
            for(DictDetail payType:payTypeList){
                if(payType.getValue().equals(spend.getSpendType())){
                    map.put("支付类型",payType.getLabel());
                }
            }
            map.put("花费人", spend.getToPerson());
            map.put("花费时间",  new Date(spend.getSpendTime().getTime()));
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }


    /**
     * 导入信息
     * @param file
     * @return
     */
    @Override
    public Map<String, Object> upload(MultipartFile file){
        /*获取支付类型的字典详情列表*/
        List<DictDetail> payTypeList = dictDetailRepository.getByDictName("pay_type");
        /*获取花费类型的字典详情列表*/
        List<DictDetail> spendTypeList = dictDetailRepository.getByDictName("spend_type");
        Map<String, Object> map = new HashMap<>();
        try {
            ExcelReader reader;
            reader=ExcelUtil.getReader(file.getInputStream());

            reader.addHeaderAlias("名称","name");
            reader.addHeaderAlias("金额","price");
            reader.addHeaderAlias("花费类型","spendType");
            reader.addHeaderAlias("支付类型","payType");
            reader.addHeaderAlias("花费人","toPerson");
            reader.addHeaderAlias("花费时间","spendTime");

            List<Spend> list = reader.readAll(Spend.class);
//            System.out.println(list);
            /*去除第一行提示的标签*/
            list.remove(0);
            List<Spend> result = new ArrayList<>();
            int count=1;
            for (Spend spendList:list) {

                if(Objects.isNull(spendList.getName())){
                    map.put("state", "error");
                    map.put("message", "第"+count+"行名称不能为空");
                    return map;
                }
                if(Objects.isNull(spendList.getPrice())){
                    map.put("state", "error");
                    map.put("message", "第"+count+"行金额不能为空");
                    return map;
                }
                if(Objects.isNull(spendList.getSpendType())){
                    map.put("state", "error");
                    map.put("message", "第"+count+"行花费类型不能为空");
                    return map;
                }

                List<DictDetail> collect1=spendTypeList.stream().filter(item->item.getLabel().equals(spendList.getSpendType())).collect(Collectors.toList());
                for (DictDetail dictDetail1:collect1) {
                    spendList.setSpendType(dictDetail1.getValue());
                }
                if(Objects.isNull(spendList.getPayType())){
                    map.put("state", "error");
                    map.put("message", "第"+count+"行支付类型不能为空");
                    return map;
                }

                List<DictDetail> collect=payTypeList.stream().filter(item->item.getLabel().equals(spendList.getPayType())).collect(Collectors.toList());
                for (DictDetail dictDetail:collect) {
                    spendList.setPayType(dictDetail.getValue());
                }

                if(Objects.isNull(spendList.getToPerson())){
                    map.put("state", "error");
                    map.put("message", "第"+count+"行花费人不能为空");
                    return map;
                }
                if(Objects.isNull(spendList.getSpendTime())){
                    map.put("state", "error");
                    map.put("message", "第"+count+"行花费时间不能为空");
                    return map;
                }

                spendList.setId(IdUtil.simpleUUID());
//                spendList.setSpendType("1");
                spendList.setCreateTime(new Timestamp(new Date().getTime()));

                result.add(spendList);
            }
            spendRepository.saveAll(result);
            map.put("state", "success");
            map.put("info", "导入" + list.size() + "条数据，成功" + result.size() + "条");

        } catch (IOException e) {

            map.put("state", "error");
            map.put("message", "导入失败");
        }
        return map;
    }

    @Override
    public void exportTemplate(HttpServletResponse response) throws IOException {
        String newFilePath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
        //模板名称
        String fileName = "信息模板";
        //设置头
        String[] headers = {"名称", "金额","花费类型", "支付类型","花费人","花费时间"};
        /*必填的列数标识*/
        Integer[] mandatory = {0, 1, 5};
        List<String> headerList = new ArrayList<>();
        for (int i = 0; i < headers.length; i++) {
            headerList.add(headers[i]);
        }
        //存放数据集
        List<List<String>> downData = new ArrayList<>();
        //数据所在列
        List<String> downRows = Lists.newArrayList();
        List<String> spendData=dictDetailRepository.getByDictName("spend_type").stream().map(DictDetail::getLabel).collect(Collectors.toList());
        List<String> payData=dictDetailRepository.getByDictName("pay_type").stream().map(DictDetail::getLabel).collect(Collectors.toList());


        downRows.add("2");
        downData.add(spendData);
        downRows.add("3");
        downData.add(payData);
        //生成待下载excel模板

        /**
         * @param
         * @param filePath Excel文件路径
         * @param
         * @param headers  Excel列标题(数组)
         * @param
         * @param downData 下拉框数据(数组)
         * @param
         * @param downRows 下拉列的序号(数组,序号从0开始)
         * @return void
         * @throws String filePath, String sheetTitle, List<String> headers, Map<String,String[]> map, String[] fatherOption
         * @Title: testFunction
         * @Description: 生成Excel导入模板
         */
        DownExcelTemp.createExcelTemplate(newFilePath, fileName, headerList, downData, downRows, mandatory, warningInfo);
        //下载模板
        DownLoadUtil.downFile(newFilePath, fileName, response);
        //删除临时文件
        File delFile = new File(newFilePath);
        if (delFile.exists()) {
            delFile.delete();
        }
    }

    @Override
    public List<Spend> getData() {
        return spendRepository.getAll();
    }

    @Override
    public List<Map<Object, Object>> getPayTypeNum(String type) {
        List <Map<Object,Object>> list = new ArrayList<>();
        /*获取消费类型*/
        List<DictDetail> typeLists = dictDetailRepository.getByDictName(type);
        for(DictDetail typeList:typeLists){
            Map<Object, Object> map = new LinkedHashMap<>();
            map.put("value",spendRepository.getPayTypeNum(typeList.getValue()));
            map.put("name",typeList.getLabel());
            map.put("sum",spendRepository.getPaySum(typeList.getValue()));

            list.add(map);
        }

        return list;
    }

    /*根据类型获取数据总值*/
    @Override
    public List<Map<Object,Object>> getSpendTypeNum(String type) {
        List <Map<Object,Object>> list = new ArrayList<>();
        /*获取消费类型*/
        List<DictDetail> typeLists = dictDetailRepository.getByDictName(type);
        for(DictDetail typeList:typeLists){
            Map<Object, Object> map = new LinkedHashMap<>();
            map.put("value",spendRepository.getSpendTypeNum(typeList.getValue()));
            map.put("name",typeList.getLabel());
            map.put("sum",spendRepository.getSpendSum(typeList.getValue()));


            list.add(map);
        }

        return list;
    }

    /**
     * 查询所有月的总数
     * @return
     */
    public List<Map<Object, Object>> monthDateList(Integer numMonth) {
        List<Map<Object,Object>> monthDateList=new ArrayList<>();
        List<String> datelist;
        datelist= DateUtils.dateArr(numMonth);


        for (int i = 0; i < datelist.size(); i++) {
            Map<Object, Object> map = new LinkedHashMap<>();
            map.put("date",datelist.get(i));
            map.put("data",spendRepository.getMonthDate(datelist.get(i)));
            monthDateList.add(map);

        }


        return monthDateList;
    }

    @Override
    public List<String> getSpendLabel() {
        List<String> typeLists = dictDetailRepository.getByDictLabel("spend_type");
        return typeLists;
    }

    public List<Map<Object, Object>> everyMonth(Integer dateNum) {
        List<Map<Object, Object>> datalist = new ArrayList<>();
            List<String> datelist;
            datelist = DateUtils.dateArr(dateNum);
            Map<Object, Object> countPrice;
            for (int i = 0; i < datelist.size(); i++) {
                countPrice = spendRepository.number(datelist.get(i));
                Object sum = countPrice.get("sum");
                Object count = countPrice.get("count");
                Map<Object, Object> map = new HashMap<>();
                if (sum == null) {
                    sum = 0;
                }
                map.put("date", datelist.get(i));
                map.put("price", sum);
                map.put("monthNumber", count);
                datalist.add(map);
              }
               Map<Object, Object> map = new HashMap<>();
               map.put("sum", spendRepository.totalSpend());
               datalist.add(map);

              return datalist;
    }

    public Integer getYearPriceSum(String year){
        return spendRepository.getYearPriceSum(year);

    }


    @Override
    public Map<String, Object> countNumberByDate(String dates) {
        Map<String, Object> map = new HashMap<>();
        List<String> dateList;
        if (StringUtils.isBlank(dates) || dates.equals("null")) {
            dateList = DateUtils.getAfewDaysToNowDate(6, "yyyy-MM-dd");
        } else {
            String[] date = dates.split(",");
            dateList = DateUtils.getDateListByStartAndEnd(date[0], date[1]);
        }
        List<Map<String, String>> list = spendRepository.getAllByDate( dateList.get(0), dateList.get(dateList.size() - 1));
        List number = new ArrayList();
        for (int i = 0; i < dateList.size(); i++) {
            for (int j = 0; j < list.size(); j++) {
                if (list.get(j).get("date").equals(dateList.get(i))) {
                    number.add(list.get(j).get("number"));
                    break;
                }
            }
            if (i + 1 != number.size()) number.add(0);
        }
        map.put("date", dateList);
        map.put("number", number);
        return map;
    }

    @Override
    public void orginToDesnate() {
        List<SpendDto> spendLists = this.queryAll(new SpendQueryCriteria());
        List<SpendDto> list = new ArrayList<>();
        for (SpendDto spendDto : spendLists){

            if(spendDto.getFilePath()!=null){
                String[] split = spendDto.getFilePath().split("\\|");
                list.add(spendDto);
                for (String s : split) {
                    if(!s.isEmpty()){
                        fileMover.orginToDesnate(s);
                    }
                }
            }
//            spendDto.setFilePath(spendDto.getFilePath().replace("图片", "backfile"));
        }
//        spendRepository.saveAll(spendMapper.toEntity(list));
    }

}